//===--- UnsafePointer.swift.gyb ------------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

%import gyb
%TMirrorDecl = gyb.parseTemplate("../common/MirrorDecl.gyb")
%TMirrorConformance = gyb.parseTemplate("../common/MirrorConformance.gyb")
%TMirrorBoilerplate = gyb.parseTemplate("../common/MirrorBoilerplate.gyb")

% for mutable in (True, False):
%  Self = 'UnsafeMutablePointer' if mutable else 'UnsafePointer'
%  a_Self = 'an `UnsafeMutablePointer`' if mutable else 'an `UnsafePointer`'
%  MirrorConformance = gyb.executeTemplate(TMirrorConformance,introspecteeType=Self,genericArgs=['Memory'],disposition='Struct')
%  MirrorDecl = gyb.executeTemplate(TMirrorDecl,introspecteeType=Self,genericArgs=['Memory'],disposition='Struct')
%  MirrorBoilerplate = gyb.executeTemplate(TMirrorBoilerplate,introspecteeType=Self,genericArgs=['Memory'],disposition='Struct')

/// A pointer to an object of type `Memory`.  This type provides no automated
/// memory management, and therefore the user must take care to allocate
/// and free memory appropriately.
///
/// The pointer should be aligned to `alignof(Memory.self)`.
///
/// The pointer can be in one of the following states:
///
/// - memory is not allocated (for example, pointer is null, or memory has
///   been deallocated previously);
///
/// - memory is allocated, but value has not been initialized;
///
/// - memory is allocated and value is initialized.
public struct ${Self}<Memory>
  : RandomAccessIndexType, Hashable,
    NilLiteralConvertible, _PointerType {

  @available(*, unavailable, renamed="Memory")
  public typealias T = Memory

  public typealias Distance = Int

  /// The underlying raw (untyped) pointer.
  public var _rawValue : Builtin.RawPointer

  /// Construct a null pointer.
  @_transparent
  public init() {
    self._rawValue = _nilRawPointer
  }

  /// Construct ${a_Self} from a builtin raw pointer.
  @_transparent
  public init(_ _rawValue : Builtin.RawPointer) {
    self._rawValue = _rawValue
  }

  /// Convert from an opaque C pointer to a typed pointer.
  ///
  /// This is a fundamentally unsafe conversion.
  @_transparent
  public init(_ other : COpaquePointer) {
    _rawValue = other._rawValue
  }

  /// Construct ${a_Self} from a given address in memory.
  ///
  /// This is a fundamentally unsafe conversion.
  @_transparent
  public init(bitPattern: Int) {
    self._rawValue = Builtin.inttoptr_Word(bitPattern._builtinWordValue)
  }

  /// Construct ${a_Self} from a given address in memory.
  ///
  /// This is a fundamentally unsafe conversion.
  @_transparent
  public init(bitPattern: UInt) {
    self._rawValue = Builtin.inttoptr_Word(bitPattern._builtinWordValue)
  }

  /// Convert from an `UnsafeMutablePointer` of a different type.
  ///
  /// This is a fundamentally unsafe conversion.
  @_transparent
  public init<U>(_ from : UnsafeMutablePointer<U>) {
    _rawValue = from._rawValue
  }

  /// Convert from a `UnsafePointer` of a different type.
  ///
  /// This is a fundamentally unsafe conversion.
  @_transparent
  public init<U>(_ from : UnsafePointer<U>) {
    _rawValue = from._rawValue
  }

  /// Create an instance initialized with `nil`.
  @_transparent public
  init(nilLiteral: ()) {
    self = ${Self}()
  }

%  if mutable:
  /// Allocate memory for `num` objects of type `Memory`.
  ///
  /// - Postcondition: The memory is allocated, but not initialized.
  @warn_unused_result
  public static func alloc(num: Int) -> ${Self} {
    let size = strideof(Memory.self) * num
    return ${Self}(
      Builtin.allocRaw(size._builtinWordValue, Builtin.alignof(Memory.self)))
  }

  /// Deallocate `num` objects.
  ///
  /// - parameter num: Number of objects to deallocate.  Should match exactly
  ///   the value that was passed to `alloc()` (partial deallocations are not
  ///   possible).
  ///
  /// - Precondition: The memory is not initialized.
  ///
  /// - Postcondition: The memory has been deallocated.
  public func dealloc(num: Int) {
    let size = strideof(Memory.self) * num
    Builtin.deallocRaw(
      _rawValue, size._builtinWordValue, Builtin.alignof(Memory.self))
  }
%  end

%{
if mutable:
    comment = """\
  /// Access the underlying raw memory, getting and setting values."""
else:
    comment = """\
  /// Access the underlying raw memory, getting values."""
}%

${comment}
  public var memory: Memory {
%  if mutable:
    @_transparent unsafeAddress {
      return UnsafePointer(self)
    }
    @_transparent nonmutating unsafeMutableAddress {
      return self
    }
%  else:
    @_transparent unsafeAddress {
      return self
    }
%  end
  }

%  if mutable:
  /// Initialize the value the pointer points to, to construct
  /// an object where there was no object previously stored.
  ///
  /// - Precondition: The memory is not initialized.
  ///
  /// - Postcondition: The memory is initalized; the value should eventually
  ///   be destroyed or moved from to avoid leaks.
  public func initialize(newvalue: Memory) {
    Builtin.initialize(newvalue, _rawValue)
  }

  /// Retrieve the value the pointer points to, moving it away
  /// from the location referenced in memory.
  ///
  /// Equivalent to reading `memory` property and calling `destroy()`,
  /// but more efficient.
  ///
  /// - Precondition: The memory is initialized.
  ///
  /// - Postcondition: The value has been destroyed and the memory must
  ///   be initialized before being used again.
  @warn_unused_result
  public func move() -> Memory {
    return Builtin.take(_rawValue)
  }

  /// Assign from `count` values beginning at source into initialized
  /// memory, proceeding from the first element to the last.
  public func assignFrom(source: ${Self}, count: Int) {
    _debugPrecondition(
      count >= 0, "assignFrom with negative count")
    _debugPrecondition(
      self < source || self >= source + count,
      "assignFrom non-following overlapping range; use assignBackwardFrom")
    for i in 0..<count {
      self[i] = source[i]
    }
  }

  /// Assign from `count` values beginning at `source` into
  /// initialized memory, proceeding from the last value to the first.
  /// Use this for assigning ranges into later memory that may overlap
  /// with the source range.
  ///
  /// - Requires: Either `source` precedes `self` or follows `self + count`.
  public func assignBackwardFrom(source: ${Self}, count: Int) {
    _debugPrecondition(
      count >= 0, "${Self}.assignBackwardFrom with negative count")
    _debugPrecondition(
      source < self || source >= self + count,
      "${Self}.assignBackwardFrom non-preceding overlapping range; use assignFrom instead")
    for var i = count; --i >= 0; {
      self[i] = source[i]
    }
  }

  /// Move `count` values beginning at source into raw memory,
  /// transforming the source values into raw memory.
  public func moveInitializeFrom(source: ${Self}, count: Int) {
    _debugPrecondition(
      count >= 0, "${Self}.moveInitializeFrom with negative count")
    _debugPrecondition(
      self < source || self >= source + count,
      "${Self}.moveInitializeFrom non-following overlapping range; use moveInitializeBackwardFrom")
    Builtin.takeArrayFrontToBack(
      Memory.self, self._rawValue, source._rawValue, count._builtinWordValue)
    // This builtin is equivalent to:
    // for i in 0..<count {
    //   (self + i).initialize((source + i).move())
    // }
  }

  /// Move `count` values beginning at `source` into uninitialized memory,
  /// transforming the source values into raw memory, proceeding from
  /// the last value to the first.  Use this for copying ranges into
  /// later memory that may overlap with the source range.
  ///
  /// - Requires: Either `source` precedes `self` or follows `self + count`.
  public func moveInitializeBackwardFrom(source: ${Self}, count: Int) {
    _debugPrecondition(
      count >= 0, "${Self}.moveInitializeBackwardFrom with negative count")
    _debugPrecondition(
      source < self || source >= self + count,
      "${Self}.moveInitializeBackwardFrom non-preceding overlapping range; use moveInitializeFrom instead")
    Builtin.takeArrayBackToFront(
      Memory.self, self._rawValue, source._rawValue, count._builtinWordValue)
    // This builtin is equivalent to:
    // var src = source + count
    // var dst = self + count
    // while dst != self {
    //   (--dst).initialize((--src).move())
    // }
  }

  /// Copy `count` values beginning at source into raw memory.
  ///
  /// - Precondition: The memory is not initialized.
  ///
  /// - Requires: `self` and `source` may not overlap.
  public func initializeFrom(source: ${Self}, count: Int) {
    _debugPrecondition(
      count >= 0, "${Self}.initializeFrom with negative count")
    _debugPrecondition(
      self + count <= source || source + count <= self,
      "${Self}.initializeFrom non-following overlapping range")
    Builtin.copyArray(
      Memory.self, self._rawValue, source._rawValue, count._builtinWordValue)
    // This builtin is equivalent to:
    // for i in 0..<count {
    //   (self + i).initialize(source[i])
    // }
  }

  /// Copy the elements of `C` into raw memory.
  ///
  /// - Precondition: The memory is not initialized.
  public func initializeFrom<
    C : CollectionType where C.Generator.Element == Memory
  >(source: C) {
    source._initializeTo(self)
  }

  /// Assign from `count` values beginning at `source` into initialized
  /// memory, transforming the source values into raw memory.
  ///
  /// - Requires: The `self` and `source` ranges may not overlap.
  public func moveAssignFrom(source: ${Self}, count: Int) {
    _debugPrecondition(
      count >= 0, "moveAssignFrom with negative count")
    _debugPrecondition(
      self + count <= source || source + count <= self,
      "moveAssignFrom overlapping range")
    Builtin.destroyArray(Memory.self, self._rawValue, count._builtinWordValue)
    Builtin.takeArrayFrontToBack(
      Memory.self, self._rawValue, source._rawValue, count._builtinWordValue)
    // These builtins are equivalent to:
    // for i in 0..<count {
    //   self[i] = (source + i).move()
    // }
  }

  /// Destroy the object the pointer points to.
  ///
  /// - Precondition: The memory is initialized.
  ///
  /// - Postcondition: The value has been destroyed and the memory must
  ///   be initialized before being used again.
  public func destroy() {
    Builtin.destroy(Memory.self, _rawValue)
  }

  /// Destroy the `count` objects the pointer points to.
  /// - Precondition: The memory is initialized.
  ///
  /// - Postcondition: The value has been destroyed and the memory must
  ///   be initialized before being used again.
  public func destroy(count: Int) {
    _debugPrecondition(count >= 0, "${Self}.destroy with negative count")
    Builtin.destroyArray(Memory.self, _rawValue, count._builtinWordValue)
  }
%  end

  @_transparent public
  var _isNull : Bool {
    return self == nil
  }

  /// Access the `i`th element of the raw array starting at `self`.
  public subscript(i: Int) -> Memory {
%  if mutable:
    @_transparent
    unsafeAddress {
      return UnsafePointer(self + i)
    }
    @_transparent
    nonmutating unsafeMutableAddress {
      return self + i
    }
%  else:
    @_transparent
    unsafeAddress {
      return self + i
    }
%  end
  }

% if mutable:
  /// If self was converted from `nil`, writes the result of invoking body into
  /// the pointee.
  public // SPI(Foundation)
  func _setIfNonNil(@noescape body: () -> Memory) {
    if self != nil {
      memory = body()
    }
  }

#if _runtime(_ObjC)
  /// Return the result of invoking body.  If self was converted from
  /// nil, passes nil as the argument.  Otherwise, passes the address
  /// of a `Memory` which is written into buffer before this method returns.
  @_transparent public
  func _withBridgeObject<U : AnyObject, R>(
    inout buffer: U?, @noescape body: AutoreleasingUnsafeMutablePointer<U?> -> R
  ) -> R {
    return self != nil ? body(&buffer) : body(nil)
  }
#endif

  /// Return the result of invoking body.  If self was converted from
  /// `nil`, passes `nil` as the argument.  Otherwise, passes the address
  /// of buffer.
  @_transparent public
  func _withBridgeValue<U, R>(
    inout buffer: U, @noescape body: UnsafeMutablePointer<U> -> R
  ) -> R {
    return self != nil ? body(&buffer) : body(nil)
  }
% end

  //
  // Protocol conformance
  //

  /// The hash value.
  ///
  /// **Axiom:** `x == y` implies `x.hashValue == y.hashValue`.
  ///
  /// - Note: The hash value is not guaranteed to be stable across
  ///   different invocations of the same program.  Do not persist the
  ///   hash value across program runs.
  public var hashValue: Int {
    return Int(Builtin.ptrtoint_Word(_rawValue))
  }
  /// Returns the next consecutive value after `self`.
  ///
  /// - Requires: The next value is representable.
  public func successor() -> ${Self} {
    return self + 1
  }
  /// Returns the previous consecutive value before `self`.
  ///
  /// - Requires: The previous value is representable.
  public func predecessor() -> ${Self} {
    return self - 1
  }

  public func distanceTo(x: ${Self}) -> Int {
    return x - self
  }

  public func advancedBy(n: Int) -> ${Self} {
    return self + n
  }
}

extension ${Self} : CustomDebugStringConvertible {
  /// A textual representation of `self`, suitable for debugging.
  public var debugDescription: String {
    return _rawPointerToString(_rawValue)
  }
}

${MirrorDecl} {
  ${MirrorBoilerplate}

  var count: Int { return 1 }

  func _getPointerValue() -> UInt64 {
    return UInt64(Int(Builtin.ptrtoint_Word(_value._rawValue)))
  }

  subscript(i: Int) -> (String, _MirrorType) {
    switch i {
    case 0: return ("pointerValue",_reflect(_getPointerValue()))
    default: _preconditionFailure("cannot extract this child index")
    }
  }

  var summary: String {
    let selfType = "${Self}"
    let ptrValue = _getPointerValue()
    if ptrValue == 0 { return "\(selfType)(nil)" }
    return "\(selfType)(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
  }

  var quickLookObject: PlaygroundQuickLook? { return .Some(.Text(summary)) }
}

${MirrorConformance}

@_transparent
@warn_unused_result
public func == <Memory>(
  lhs: ${Self}<Memory>, rhs: ${Self}<Memory>
) -> Bool {
  return Bool(Builtin.cmp_eq_RawPointer(lhs._rawValue, rhs._rawValue))
}

@_transparent
@warn_unused_result
public func < <Memory>(lhs: ${Self}<Memory>, rhs: ${Self}<Memory>) -> Bool {
  return Bool(Builtin.cmp_ult_RawPointer(lhs._rawValue, rhs._rawValue))
}

@_transparent
@warn_unused_result
public func + <Memory>(lhs: ${Self}<Memory>, rhs: Int) -> ${Self}<Memory> {
  return ${Self}(Builtin.gep_Word(
    lhs._rawValue, (rhs &* strideof(Memory.self))._builtinWordValue))
}

@_transparent
@warn_unused_result
public func + <Memory>(lhs: Int,
           rhs: ${Self}<Memory>) -> ${Self}<Memory> {
  return rhs + lhs
}

@_transparent
@warn_unused_result
public func - <Memory>(lhs: ${Self}<Memory>, rhs: Int) -> ${Self}<Memory> {
  return lhs + -rhs
}

@_transparent
@warn_unused_result
public func - <Memory>(lhs: ${Self}<Memory>, rhs: ${Self}<Memory>) -> Int {
  return
    Int(Builtin.sub_Word(Builtin.ptrtoint_Word(lhs._rawValue),
                         Builtin.ptrtoint_Word(rhs._rawValue)))
    / strideof(Memory.self)
}

@_transparent
public func += <Memory>(inout lhs: ${Self}<Memory>, rhs: Int) {
  lhs = lhs + rhs
}

@_transparent
public func -= <Memory>(inout lhs: ${Self}<Memory>, rhs: Int) {
  lhs = lhs - rhs
}
% end # for mutable

/// A byte-sized thing that isn't designed to interoperate with
/// any other types; it makes a decent parameter to
/// `UnsafeMutablePointer<Memory>` when you just want to do bytewise
/// pointer arithmetic.
public struct RawByte {
  let _inaccessible: UInt8
}

// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End:

